package com.flyco.modules.stm.controller;

import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.flyco.modules.stm.entity.StmChannelInfo;
import com.flyco.modules.stm.entity.StmStoreInfo;
import com.flyco.modules.stm.mapper.StmStoreInfoMapper;
import com.flyco.modules.stm.model.DataxResultModel;
import com.flyco.modules.stm.model.DealerDiscountExcelDTO;
import com.flyco.modules.stm.model.DealerDiscountExcelVO;
import com.flyco.modules.stm.model.DiscountApproveDTO;
import com.flyco.modules.stm.service.IStmChannelInfoService;
import com.flyco.modules.stm.service.IStmStoreInfoService;
import io.netty.util.internal.StringUtil;
import org.apache.shiro.SecurityUtils;
import com.flyco.poi.excel.ExcelImportUtil;
import com.flyco.poi.excel.def.NormalExcelConstants;
import com.flyco.poi.excel.entity.ExportParams;
import com.flyco.poi.excel.entity.ImportParams;
import com.flyco.poi.excel.view.EntityExcelView;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.query.QueryGenerator;
import com.flyco.modules.stm.entity.StmDealerDiscount;
import com.flyco.modules.stm.vo.StmDealerDiscountPage;
import com.flyco.modules.stm.service.IStmDealerDiscountService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.flyco.common.aspect.annotation.AutoLog;

/**
 * @Description: 经销商折扣表
 * @Author: flyco
 * @Date: 2024-04-11
 * @Version: V1.0
 */
@Api(tags = "经销商折扣表")
@RestController
@RequestMapping("/f/stm/stmDealerDiscount")
@Slf4j
public class StmDealerDiscountController {
    @Autowired
    private IStmDealerDiscountService stmDealerDiscountService;
    @Autowired
    private IStmStoreInfoService storeInfoService;
    @Autowired
    private IStmChannelInfoService channelInfoService;
    @Autowired
    private StmStoreInfoMapper storeInfoMapper;

    /**
     * 分页列表查询
     *
     * @param stmDealerDiscount
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "经销商折扣表-分页列表查询")
    @ApiOperation(value = "经销商折扣表-分页列表查询", notes = "经销商折扣表-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(StmDealerDiscount stmDealerDiscount,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<StmDealerDiscount> queryWrapper = QueryGenerator.initQueryWrapper(stmDealerDiscount, req.getParameterMap());
        Page<StmDealerDiscount> page = new Page<StmDealerDiscount>(pageNo, pageSize);
        if (!StringUtil.isNullOrEmpty(stmDealerDiscount.getStoreName()) || !StringUtil.isNullOrEmpty(stmDealerDiscount.getSaleRealName())) {
            QueryWrapper<StmStoreInfo> storeQuery = new QueryWrapper<StmStoreInfo>();
            if (!StringUtil.isNullOrEmpty(stmDealerDiscount.getStoreName())) {
                storeQuery.like("name", stmDealerDiscount.getStoreName());
            }
            if (!StringUtil.isNullOrEmpty(stmDealerDiscount.getSaleRealName())) {
                storeQuery.like("sale_real_name", stmDealerDiscount.getSaleRealName());
            }
            List<StmStoreInfo> storeInfoList = storeInfoMapper.selectList(storeQuery);
            if (storeInfoList != null && !storeInfoList.isEmpty()) {
                queryWrapper.in("store_id", storeInfoList.stream().map(x -> x.getCompanyCode()).collect(Collectors.toList()));
            } else {
                List<String> storeIdList = new ArrayList<>();
                storeIdList.add("0");
                queryWrapper.in("store_id", storeIdList);
            }
        }
        IPage<StmDealerDiscount> pageList = stmDealerDiscountService.page(page, queryWrapper);
        List<String> channelIdList = pageList.getRecords().stream().map(StmDealerDiscount::getChannelCode).distinct().collect(Collectors.toList());
        //如果列表不为空，根据渠道code查询name
        if (!CollectionUtils.isEmpty(channelIdList)) {
            Map<String, StmChannelInfo> channelInfoMap = channelInfoService.getByChannelIds(channelIdList).stream().collect(Collectors.toMap(StmChannelInfo::getChannelId, a -> a));
            pageList.getRecords().forEach(o -> {
                if (channelInfoMap.get(o.getChannelCode()) != null) {
                    o.setChannelName(channelInfoMap.get(o.getChannelCode()).getName());
                }
                List<StmStoreInfo> storeList = storeInfoMapper.selectList(new QueryWrapper<StmStoreInfo>()
                        .eq("company_code", o.getStoreId())
                        .eq("channel_id", o.getChannelCode())
                        .eq("partner_id", o.getCompanyCode()));
                if (storeList != null && !storeList.isEmpty()) {
                    o.setStoreName(storeList.get(0).getName());
                }
            });
        }
        return Result.ok(pageList);
    }

    /**
     * 添加
     *
     * @param stmDealerDiscountPage
     * @return
     */
    @AutoLog(value = "经销商折扣表-添加")
    @ApiOperation(value = "经销商折扣表-添加", notes = "经销商折扣表-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody StmDealerDiscountPage stmDealerDiscountPage) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        List<StmDealerDiscount> list = new ArrayList<>();
        for (String storeId : stmDealerDiscountPage.getStoreIdList()) {
            StmDealerDiscount stmDealerDiscount = new StmDealerDiscount();
            BeanUtils.copyProperties(stmDealerDiscountPage, stmDealerDiscount);

            stmDealerDiscount.setProductAmount(stmDealerDiscountPage.getProductAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getProductAmount());
            stmDealerDiscount.setMissionAmount(stmDealerDiscountPage.getMissionAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getMissionAmount());
            stmDealerDiscount.setPromotionAmount(stmDealerDiscountPage.getPromotionAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getPromotionAmount());
            stmDealerDiscount.setAdjustAmount(stmDealerDiscountPage.getAdjustAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getAdjustAmount());

            stmDealerDiscount.setProductRemainAmount(stmDealerDiscount.getProductAmount());
            stmDealerDiscount.setPromotionRemainAmount(stmDealerDiscount.getPromotionAmount());
            stmDealerDiscount.setMissionRemainAmount(stmDealerDiscount.getMissionAmount());
            stmDealerDiscount.setAdjustRemainAmount(stmDealerDiscount.getAdjustAmount());
            stmDealerDiscount.setStoreId(storeId);
            stmDealerDiscount.setAuditStatus(0);
            stmDealerDiscount.setCreateBy(sysUser.getUsername());
            stmDealerDiscount.setCreateTime(DateTime.now());
            StmStoreInfo storeInfo = storeInfoService.getByStoreId(Long.valueOf(storeId));
            stmDealerDiscount.setChannelCode(storeInfo.getChannelId());
            stmDealerDiscount.setCompanyCode(storeInfo.getCompanyCode().toString());

            //先判断在时间区间内是否已有折扣优惠，如果有不允许提交。
            List<StmDealerDiscount> discountList = stmDealerDiscountService.getDiscountByStoreIdAndTime(stmDealerDiscount.getStoreId(), stmDealerDiscountPage.getStartTime(), stmDealerDiscountPage.getEndTime(), stmDealerDiscount.getCompanyCode(), stmDealerDiscount.getChannelCode());
            if (!CollectionUtils.isEmpty(discountList)) {
                return Result.error("经销商在选择的时间段内已有折扣活动，无法继续添加！");
            }

            list.add(stmDealerDiscount);
        }

        stmDealerDiscountService.saveBatch(list, list.size());
        return Result.ok("添加成功！");
    }


    /**
     * 编辑
     *
     * @param stmDealerDiscountPage
     * @return
     */
    @AutoLog(value = "经销商折扣表-编辑")
    @ApiOperation(value = "经销商折扣表-", notes = "经销商折扣表-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody StmDealerDiscountPage stmDealerDiscountPage) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<Long> idList = Arrays.asList(stmDealerDiscountPage.getIds().split(",")).stream().map(o -> {
            Long id = Long.valueOf(o);
            return id;
        }).collect(Collectors.toList());


        List<StmDealerDiscount> list = new ArrayList<>();
        for (Long id : idList) {
            StmDealerDiscount stmDealerDiscount = stmDealerDiscountService.getById(id);
            stmDealerDiscount.setProductAmount(stmDealerDiscountPage.getProductAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getProductAmount());
            stmDealerDiscount.setMissionAmount(stmDealerDiscountPage.getMissionAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getMissionAmount());
            stmDealerDiscount.setPromotionAmount(stmDealerDiscountPage.getPromotionAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getPromotionAmount());
            stmDealerDiscount.setAdjustAmount(stmDealerDiscountPage.getAdjustAmount() == null ? BigDecimal.ZERO : stmDealerDiscountPage.getAdjustAmount());

            stmDealerDiscount.setProductRemainAmount(stmDealerDiscount.getProductAmount());
            stmDealerDiscount.setPromotionRemainAmount(stmDealerDiscount.getPromotionAmount());
            stmDealerDiscount.setMissionRemainAmount(stmDealerDiscount.getMissionAmount());
            stmDealerDiscount.setAdjustRemainAmount(stmDealerDiscount.getAdjustAmount());

            stmDealerDiscount.setStartTime(stmDealerDiscountPage.getStartTime());
            stmDealerDiscount.setEndTime(stmDealerDiscountPage.getEndTime());
            stmDealerDiscount.setAuditStatus(0);
            stmDealerDiscount.setUpdateBy(sysUser.getUsername());
            stmDealerDiscount.setUpdateTime(DateTime.now());
            list.add(stmDealerDiscount);
        }

        for (StmDealerDiscount discountInfo : list) {
            //先判断在时间区间内是否已有折扣优惠，如果有不允许提交。
            List<StmDealerDiscount> discountList = stmDealerDiscountService.getDiscountByStoreIdAndTime(discountInfo.getStoreId(), stmDealerDiscountPage.getStartTime(), stmDealerDiscountPage.getEndTime(), discountInfo.getCompanyCode(), discountInfo.getChannelCode());
            if (!CollectionUtils.isEmpty(discountList)) {
                //排除编辑的折扣活动
                discountList.removeIf(o -> o.getId().equals(discountInfo.getId()));
                if (!CollectionUtils.isEmpty(discountList)) {
                    return Result.error("经销商在选择的时间段内已有折扣活动，无法继续添加！");
                }
            }
        }

        stmDealerDiscountService.updateBatchById(list, list.size());

        return Result.ok("编辑成功!");
    }


    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "经销商折扣表-通过id删除")
    @ApiOperation(value = "经销商折扣表-通过id删除", notes = "经销商折扣表-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        stmDealerDiscountService.delMain(id);
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "经销商折扣表-批量删除")
    @ApiOperation(value = "经销商折扣表-批量删除", notes = "经销商折扣表-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.stmDealerDiscountService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");
    }

    /**
     * 添加
     *
     * @param approveDTO
     * @return
     */
    @AutoLog(value = "经销商折扣表-批量审核")
    @ApiOperation(value = "经销商折扣表-批量审核", notes = "经销商折扣表-批量审核")
    @PostMapping(value = "/auditBatch")
    public Result<?> auditBatch(@RequestBody DiscountApproveDTO approveDTO) {
        if (!StringUtil.isNullOrEmpty(approveDTO.getIds()) && approveDTO.getAuditType() != null) {
            stmDealerDiscountService.auditBatch(approveDTO);
        } else {
            return Result.fail("未选择数据或审核类型为空！");
        }
        return Result.ok("审核成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "经销商折扣表-通过id查询")
    @ApiOperation(value = "经销商折扣表-通过id查询", notes = "经销商折扣表-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        StmDealerDiscount stmDealerDiscount = stmDealerDiscountService.getById(id);
        return Result.ok(stmDealerDiscount);
    }


    /**
     * 导出excel
     *
     * @param request
     * @param stmDealerDiscount
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, StmDealerDiscount stmDealerDiscount) {
        // Step.1 组装查询条件
        QueryWrapper<StmDealerDiscount> queryWrapper = QueryGenerator.initQueryWrapper(stmDealerDiscount, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<DealerDiscountExcelVO> pageList = new ArrayList<DealerDiscountExcelVO>();
        List<StmDealerDiscount> stmDealerDiscountList = stmDealerDiscountService.list(queryWrapper);

        List<String> channelIdList = stmDealerDiscountList.stream().map(StmDealerDiscount::getChannelCode).distinct().collect(Collectors.toList());

        Map<String, StmChannelInfo> channelInfoMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(channelIdList)) {
            //如果列表不为空，根据渠道code查询name
            channelInfoMap = channelInfoService.getByChannelIds(channelIdList).stream().collect(Collectors.toMap(StmChannelInfo::getChannelId, a -> a));
        }
        for (StmDealerDiscount temp : stmDealerDiscountList) {
            DealerDiscountExcelVO vo = new DealerDiscountExcelVO();
            BeanUtils.copyProperties(temp, vo);
            if (channelInfoMap.get(temp.getChannelCode()) != null) {
                vo.setChannelName(channelInfoMap.get(temp.getChannelCode()).getName());
            }
            pageList.add(vo);
        }
        //Step.3 调用AutoPoi导出Excel
        ModelAndView mv = new ModelAndView(new EntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "经销商折扣表");
        mv.addObject(NormalExcelConstants.CLASS, DealerDiscountExcelVO.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("经销商折扣表数据", "导出人:" + sysUser.getRealname(), "经销商折扣表"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {

                Map<String, StmChannelInfo> channelInfoMap = channelInfoService.getChannelList().stream().collect(Collectors.toMap(StmChannelInfo::getChannelId, a -> a));
                Map<Long, StmStoreInfo> storeInfoMap = storeInfoService.getStoreList().stream().collect(Collectors.toMap(StmStoreInfo::getStoreId, a -> a));

                List<DealerDiscountExcelDTO> list = ExcelImportUtil.importExcel(file.getInputStream(), DealerDiscountExcelDTO.class, params);
                List<StmDealerDiscount> dealerDiscountList = new ArrayList<>();
                StringBuilder sb = new StringBuilder(10);
                for (DealerDiscountExcelDTO discountDTO : list) {
                    //对数据进行有效性判断
                    if (channelInfoMap.get(discountDTO.getChannelCode()) == null) {
                        sb.append("渠道错误,根据渠道id：" + discountDTO.getChannelCode() + "未找到渠道信息;");
                    }
                    if (storeInfoMap.get(Long.valueOf(discountDTO.getStoreId())) == null) {
                        sb.append("经销商编码错误,根据编码：" + discountDTO.getStoreId() + "未找到经销商信息;");
                    }
                    StmDealerDiscount po = new StmDealerDiscount();
                    BeanUtils.copyProperties(discountDTO, po);
                    po.setStartTime(DateUtil.beginOfDay(discountDTO.getStartTime()));
//                    po.setEndTime(DateUtil.endOfDay(discountDTO.getEndTime())); //保存后变成第二天了
                    po.setEndTime(DateUtil.parse(DateUtil.format(discountDTO.getEndTime(), "yyyy-MM-dd") + " 23:59:59"));
                    po.setAuditStatus(0);
                    dealerDiscountList.add(po);
                }
                if (sb.length() > 0) {
                    return Result.error("文件导入失败。" + sb.toString());
                }

                for (StmDealerDiscount discountInfo : dealerDiscountList) {
                    //先判断在时间区间内是否已有折扣优惠，如果有不允许提交。
                    List<StmDealerDiscount> discountList = stmDealerDiscountService.getDiscountByStoreIdAndTime(discountInfo.getStoreId(), discountInfo.getStartTime(), discountInfo.getEndTime(), discountInfo.getCompanyCode(), discountInfo.getChannelCode());
                    if (!CollectionUtils.isEmpty(discountList)) {
                        return Result.error("经销商在选择的时间段内已有折扣活动，无法继续添加！");
                    }
                }

                if (!CollectionUtils.isEmpty(dealerDiscountList)) {
                    stmDealerDiscountService.saveBatch(dealerDiscountList, dealerDiscountList.size());
                }
                return Result.ok("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.ok("文件导入失败！");
    }

    @RequestMapping(value = "/download")
    public void download(HttpServletRequest req, HttpServletResponse res) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {

            inputStream = this.getClass().getResourceAsStream("/templates/discountTemplate.xlsx");
            outputStream = res.getOutputStream();
            int temp = 0;
            while ((temp = inputStream.read()) != -1) {
                outputStream.write(temp);
            }
            res.setContentType("application/force-download");// 设置强制下载不打开
            res.addHeader("Content-Disposition", "attachment;fileName=" + new String("折扣导入模板.xlsx".getBytes("UTF-8"), "iso-8859-1"));
            res.setHeader("content-type", "text/html;charset=UTF-8");
            res.setCharacterEncoding("UTF-8");
        } catch (Exception e) {
            log.error("", e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return;
    }

    /**
     * 手工同步折扣信息
     *
     * @param jobId 任务ID
     * @return
     */
    @AutoLog(value = "经销商折扣表-手工同步")
    @ApiOperation(value = "经销商折扣表-手工同步", notes = "经销商折扣表-手工同步")
    @GetMapping(value = "/syncDiscount")
    public Result<?> syncDiscount(@RequestParam(name = "jobId") String jobId) {
        String loginUrl = "http://192.168.20.31:9527/api/auth/login";
        String input = "{\"username\":\"20200356\",\"password\":\"lihan123\",\"rememberMe\":1}";
        String loginResult = getPostResult(loginUrl, input, "");
        if (!StringUtil.isNullOrEmpty(loginResult)) {
            JSONObject loginJson = JSONObject.parseObject(loginResult);
            String token = loginJson.toJavaObject(DataxResultModel.class).getContent().getData();
            if (!StringUtil.isNullOrEmpty(token)) {
                String jobUrl = "http://192.168.20.31:9527/api/job/trigger";
                String jobParam = "{\"jobId\":" + jobId + ",\"executorParam\":\"\"}";
                String jobResult = getPostResult(jobUrl, jobParam, token);
                if (!StringUtil.isNullOrEmpty(jobResult)) {
                    String newResult = jobResult;

                }
            }
        }
        return Result.ok("操作成功");
    }

    //通过Post请求操作Datax
    private String getPostResult(String url, String paramString, String token) {
        String result = "";
        try {
            URL postUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) postUrl.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);

            // 设置请求头，例如内容类型
            conn.setRequestProperty("Content-Type", "application/json");
            if (!StringUtil.isNullOrEmpty(token)) {
                conn.setRequestProperty("Authorization", token);
            }
            try (OutputStream os = conn.getOutputStream()) {
                byte[] inputBytes = paramString.getBytes();
                os.write(inputBytes);
            }
            // 获取响应码
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                // 读取响应
                StringBuffer respResult = new StringBuffer();
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                String line;
                while ((line = reader.readLine()) != null) {
                    respResult.append(line);
                }
                reader.close();
                result = respResult.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}
